#include "utility.hpp"

#include "condition.hpp"

namespace mina
{
	namespace thread
	{
		IMPL_LOGGER(Condition, logger);

		Condition::Condition()
		{
			int ret = 0;
			if ((ret = ::pthread_cond_init(&_cond, 0)) != 0)
			{
				LOG4CPLUS_ERROR(logger, "Condition::Condition pthread_cond_init error. errno: " << ret);
			}
		}

		Condition::~Condition()
		{
			int ret = 0;
			if ((ret = ::pthread_cond_destroy(&_cond)) != 0)
			{
				LOG4CPLUS_ERROR(logger, "Condition::~Condition pthread_cond_destroy error. errno: " << ret);
			}
		}

		void Condition::wait(Lock & lock)
		{
			int ret = 0;
			if ((ret = ::pthread_cond_wait(&_cond, &lock._mutex)) != 0)
			{
				LOG4CPLUS_ERROR(logger, "Condition::wait pthread_cond_wait error. errno: " << ret);
			}
		}

		bool Condition::wait(Lock & lock, long ms)
		{
			struct timespec spec;
			Utility::get_abs_timespec(ms, spec);

			int ret = ::pthread_cond_timedwait(&_cond, &lock._mutex, &spec);

			if (ETIMEDOUT == ret)
			{
				return false;
			}

			if (0 != ret)
			{
				LOG4CPLUS_ERROR(logger, "Condition::wait(long ms) pthread_cond_timewait error. errno: " << ret);
			}

			return (0 == ret);
		}

		void Condition::signal()
		{
			int ret = 0;
			if ((ret = ::pthread_cond_signal(&_cond)) != 0)
			{
				LOG4CPLUS_ERROR(logger, "Condition::signal pthread_cond_signal error. errno: " << ret);
			}
		}

		void Condition::brocast()
		{
			int ret = 0;
			if ((ret = ::pthread_cond_broadcast(&_cond)) != 0)
			{
				LOG4CPLUS_ERROR(logger, "Condition::brocast pthread_cond_brocast error. errno: " << ret);
			}
		}
	}
}
